昨天我們已經創建了第一條 CI/CD Pipeline,但實際上在 script:
中我們並沒有撰寫什麼真實可用的動作。接續昨天的進度,今天繼續說明 CI/CD Pipeline 中的那些辛苦麻煩事。
在繼續說明之前,先幫大家恢復一下記憶並說明目前 CI/CD 的環境現況。
我們假設的案例情境是,這是一個全新建立的開發團隊,並且即將要開發一項全新的產品。在目前萬事待舉的狀態下,我們的主角 Dev Leader 決定先用熟悉的老方法來建立初期的 CI/CD Pipeline,因此目前 CI/CD 的環境將如下圖所示:
build
。build
完成的程式 deploy
至 Dev 與 Stg Server。前情提要完畢,下面就開始今天的進度。
相信大家都知道,並不是你將任何的 Source Code 放在 Server 上,該程式就直接能夠運行。有些程式語言需要事先 Compile,有一些則是有許多的 Dependency 需要處理。因此不管是 Compiled Language 或 Interpreted Language,通常 CI Pipeline 的第一個 Stage/Job
多半都會是 Build
,透過 Build
將你的程式從無法運行的 Source Code 轉變成一包只要 Deploy 至 Server 之後即可運行的程式。
舉例來說,如果是需要 Compile 的程式碼,很可能 Build
的 CI Job 會如下範例:
compile:
stage: build
tags:
- "build"
script:
- ./configure
- make
如果是有相依其他 Package 或 Library 的程式碼,例如目前 PHP 熱門 Framework 之一的 Laravel,則可能會如下範例:
laravel-build:
stage: build
tags:
- "build"
script:
- composer install
- npm install
- npm run production
(Composer 是 PHP 的 Dependency Manager,composer install
會根據 composer.json
及 composer.lock
去抓取相依的 PHP Packages。)
不管是上述哪一種,總之在 script:
你需要撰寫的就是這些 Compile 或抓取相依 Packages 的指令,讓 GitLab Runner 幫你自動執行這些指令,將 Source Code 轉變成可以運行的程式。
當 Source Code 經過 build
變成可運行的程式後,這些程式(檔案)即可被稱為是 Artifacts(產出物)。Artifacts 需要被管理、儲存,不然輪到下一個 Stage/Job
即 deploy
時,GitLab Runner 會不知道該部署哪些檔案。
因此前面的範例,很可能需要修改成下面的模樣:
compile:
stage: build
tags:
- "build"
script:
- ./configure
- make
- export CI_COMMIT=$(echo $CI_BUILD_REF | cut -b 1-6)
- export ARTIFACT_NAME="$CI_PROJECT_NAME"-"$CI_COMMIT"
- mv bin/compiled-code /artifacts/$ARTIFACT_NAME
我們假設負責 build
的 GitLab Runner 該 Server 同時也兼作存放 Artifacts 的 Server,因此 Source Code 編譯產生的 Artifacts,可以直接用 Command mv
搬移到指定的路徑,並且修改 Artifacts 的檔名以吻合規定的命名規則進行歸檔。等到 Runner 要執行 deploy
的 CI Job 時,我們就可以指定它去該路徑下取得特定的 Artifacts 進行部署的動作。
續上,如果是 Laravel 的範例,則可能會修改為:
laravel-build:
stage: build
tags:
- "build"
script:
- composer install
- npm install
- npm run production
- export CI_COMMIT=$(echo $CI_BUILD_REF | cut -b 1-6)
- export ARTIFACT_NAME="$CI_PROJECT_NAME"-"$CI_COMMIT".tar.gz
- cd ..
- tar -zc $CI_PROJECT_NAME -f /artifacts/$ARTIFACT_NAME
因為是 PHP 包含多個檔案,因此將整個資料夾用 tar
打包為 .tar.gz
進行 Artifacts 的歸檔。
在前面的範例中,我們假設 Artifacts 是直接存放在 GitLab Runner 該 Server 的 /artifacts/
路徑之下,算是必須要自己想辦法管理 Artifacts。但其實不用這麼麻煩,因為 GitLab CI 目前已經有名為 Jobs Artifacts 的功能,能夠幫助我們管理 CI Pipeline 各 Stage
所產生的 Artifacts。
讓我們繼續修改前面的範例,套用 GitLab CI 的 Job Artifacts:
compile:
stage: build
tags:
- "build"
script:
- ./configure
- make
artifacts:
paths:
- bin/compiled-code
# 節省版面,兩個範例放在一起
laravel-build:
stage: build
tags:
- "build"
script:
- composer install
- npm install
- npm run production
artifacts:
paths:
- ./
expire_in: 1 week
如上範例,原本我們寫在 script:
中的那些動作都可以省去了,只要在 artifacts:
中指定 path:
即可完成歸檔,也不需要自己 tar
將資料夾打包,只要直接指定資料夾的路徑,其中所有的檔案都會被自動歸檔為 Artifacts。除此之外,甚至可以直接在 artifacts:
中設定 expire_in:
,藉此控制 Artifacts 要保留多久的時間,免除自行管理 Artifacts 時需要煩惱檔案保存週期的問題。
(如正確設定了 artifacts:
,即可在 GitLab CI 的 Job 頁面右欄發現 Job artifacts
,User 亦可以手動 Download 或直接在線上查看 Artifacts 的內容。另外,在左欄中也會發現自動多了 Uploading artifacts
的動作。)
(查看後續的 CI Job - deploy,也會發現 GitLab CI 自動多了 Downloading artifacts
的動作。)
今天我們試著認識了 CI Pipeline 的第一個 Stage - Build,透過它將 Source Code 變成真正能夠運行的程式,在這個 Stage 有哪些關鍵問題需要處理呢?
build
的能力?舉例來說如果要 Compile C++,那麼 CI Server 上是否已經安裝好 gcc 或其他編譯所需的 library?同理,如果是 PHP,那麼 CI Server 是否已安裝為 php 環境,並且安裝好 Composer 這套 PHP 的 Dependency Manager 呢?build
的過程中是否會產生某些暫存檔案,這些檔案是否也要一併打包為 Artifacts?Build
是 CI/CD Pipeline 重要的第一步,而 Artifacts Management(產出物管理)則是隱藏在 CI/CD Pipeline 背後的重要觀念,能否將 Artifacts 管理好,對於 CI/CD 是至關重要的。其實 Artifacts Management 本身就足夠作為鐵人賽 30 天的一個主題,但今天我們就先在此打住,隨著假想情境的推進,後續(應該)還會有機會說明更多相關的內容。
鐵人賽,我們明天見~
自 2021 年 12 月 12 日開始,我就一直想要將原發佈在 iT 邦幫忙的鐵人賽系列文章搬移至 https://gitlab-book.tw 並補充說明文章內容已有過期之處。
因為當初參加 iThome 鐵人賽時,GitLab 仍在 12 版,但如今 GitLab 已更新好幾版了,需要提醒大家注意一下。
本文已完成搬遷